#include "digits_container.h"

digits_container::digits_container(const digits_container& x):
   size_(x.size_),
   capacity_(x.capacity_)
{
   if (capacity_ == 1)
   {
      digits_.digit_ = x.digits_.digit_;
   } 
   else
   {
      digits_.digits_ = new long long[capacity_];
      for (int i = 0; i < size_; i++)
      {
         digits_.digits_[i] = x.digits_.digits_[i];
      }
   }
}

int digits_container::size() const
{
   return size_;
}

void digits_container::push_back(long long x)
{   
   reserve(size_ + 1);
   (*this)[size_] = x;
   size_++;
}

void digits_container::pop_back()
{
   size_--;
   shrink();
}

void digits_container::resize(int size)
{
   reserve(size);
   
   for (int i = size_; i < size; i++)
   {
      (*this)[i] = 0;
   }

   size_ = size;
   shrink(); 
}

void digits_container::swap(digits_container& a)
{
   std::swap(size_, a.size_);
   std::swap(capacity_, a.capacity_);
   std::swap(digits_, a.digits_);
}

long long digits_container::back()
{
   return digits_.digits_[size_ - 1];
}

long long& digits_container::operator[](int i)
{
   if (capacity_ == 1)
      return digits_.digit_;

   return digits_.digits_[i];
}

long long digits_container::at(int i) const
{
   if (i >= size_)
      return 0;

   if (capacity_ == 1)
      return digits_.digit_;

   return digits_.digits_[i];
}

digits_container digits_container::operator=(digits_container x)
{
   swap(x);
   return *this;
}

void digits_container::reserve(int size)
{
   if (size <= capacity_)
      return;

   int new_capacity = capacity_ * 2;
   while (size > new_capacity)
      new_capacity *= 2;
   digits_container temporary;
   temporary.size_ = size_;
   temporary.capacity_ = new_capacity;
   temporary.digits_.digits_ = new long long[new_capacity];
   if (capacity_ == 1)
   {
      temporary.digits_.digits_[0] = digits_.digit_;
   } 
   else
   {
      for (int i = 0; i < size_; i++)
      {
         temporary.digits_.digits_[i] = digits_.digits_[i];
      }
   }

   swap(temporary);
}

void digits_container::shrink()
{
   if ((size_ <= 1) && (capacity_ == 1))
      return;

   if ((size_ <= 1) && (capacity_ > 1))
   {
      long long value = digits_.digits_[0];
      delete[] digits_.digits_;
      digits_.digit_ = value;
      capacity_ = 1;
      
      return;
   }

   if (size_ * 4 >= capacity_)
      return;

   int new_capacity = capacity_ / 2;

   while (size_ > new_capacity)
      new_capacity /= 2;

   digits_container temporary;
   temporary.size_ = size_;
   temporary.capacity_ = new_capacity;
   temporary.digits_.digits_ = new long long[new_capacity];
   if (capacity_ == 1)
   {
      temporary.digits_.digits_[0] = digits_.digit_;
   } 
   else
   {
      for (int i = 0; i < size_; i++)
      {
         temporary.digits_.digits_[i] = digits_.digits_[i];
      }
   }

   swap(temporary);
}

 digits_container::~digits_container()
{
   if (capacity_ > 1)
      delete[] digits_.digits_; 
}